---
description: Disabling root fields
keywords:
  - hasura
  - docs
  - permissions
  - rules
  - root fields
  - disable
sidebar_position: 50
---

import Thumbnail from '@site/src/components/Thumbnail';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Root Field Visibility

## Introduction

Sometimes you may want a role to only have access to certain root fields of a table or have the table only be
accessible through a [relationship](/schema/postgres/table-relationships/index.mdx).

When you track a table in Hasura Engine, all the GraphQL root fields available to the role are exposed. Ie: Under
the `query` root field: `select`, `select_by_pk` and `select_aggregate` are exposed. Under the `subscription`
root field, `select`, `select_by_pk`, `select_aggregate` and `select_stream` are exposed. Root field visibility can
disable specific query and subscription root fields.

:::info Supported from

Root field visibility is supported in version `v2.8.0` and above.

:::

<Tabs groupId="user-preference" className="api-tabs">

<TabItem value="console" label="Console">

You can disable specific root fields for queries and subscriptions by unchecking them in the Select permission for the
table and role in Console. This is located in the Console under **Data -> {table} -> Permissions -> {role} ->
select -> Root fields permissions **

<Thumbnail
  src="/img/auth/disable-root-fields_console_2.11.1.png"
  alt="Disable root fields in Hasura Console"
  width="600px"
/>

</TabItem>
<TabItem value="cli" label="CLI">

You can disable root fields for queries and subscriptions specifying which are available for the `select_permissions` by
updating the specific `metadata -> databases -> [database-name] -> tables -> [table-name].yaml` file eg:

```yaml {10-15}
table:
  name: users
  schema: public
select_permissions:
  - role: user
    permission:
      columns:
        - id
      filter: {}
      query_root_fields:
        - select_by_pk
      subscription_root_fields:
        - select
        - select_by_pk
        - select_aggregate
delete_permissions:
  - role: user
  permission:
    backend_only: true
    filter: {}
```

:::tip Nulls and empty arrays

Setting the value of `query_root_fields` or `subscription_root_fields` to `null` or not defining it at all implies that
all fields are allowed and an empty array means no fields are allowed.

:::

</TabItem>
<TabItem value="api" label="API">

You can disable root fields for Select permissions with the

[permissions Metadata API](/api-reference/metadata-api/permission.mdx) by specifying which should be available in
the `query_root_fields` and `subscription_root_fields` arrays, eg:

```http {16,17}
POST /v1/metadata HTTP/1.1
Content-Type: application/json
X-Hasura-Role: admin

{
  "type" : "pg_create_select_permission",
  "args" : {
    "table" : "users",
    "role" : "user",
    "source": "default",
    "permission" : {
      "columns" : "*",
      "filter" : {
        "is_public": true
      },
      "query_root_fields": ["select_by_pk"],
      "subscription_root_fields": ["select", "select_by_pk"]
    }
  }
}
```

:::tip Nulls and empty arrays

Setting the value of `query_root_fields` or `subscription_root_fields` to `null` or not defining it at all implies that
all fields are allowed and an empty array means no fields are allowed.

:::

</TabItem>
</Tabs>

## Root field visibility use cases

### Allow a table to be accessible only through a relationship

Let's say we have two tables, `categories` and `products` defined as follows:

| Table      | Columns                              | Relationships                     |
|------------|--------------------------------------|-----------------------------------|
| categories | `id`, `name`                         | products (array relationship)     |
| products   | `id`, `name`, `description`, `price` | category (object relationship)    |


We would like to configure permissions of the `guest` role such that they are only able to access the `products` of the
`categories` which they can access i.e. access the `products` table only through the `categories` -> `products`
relationship.

Modifying the select permission of the `products` table:

<Thumbnail
  src="/img/auth/disable-all-root-fields_console_2.11.1.png"
  alt="Disable root fields in Hasura Console"
  width="600px"
/>

Now that no `query_root_fields` or `subscription_root_fields` are enabled, the `guest` role won't be able to access
the `products` table directly and can only access the `products` table through the `categories` -> `products`
relationship.

<Thumbnail
  src="/img/auth/authorization_root-field-visibility-api-query_2-16.png"
  alt="Query with disabled root fields"
/>

:::warning Row permission considerations

If root fields are disabled then you may want to simplify the row filter permissions by giving it "without any checks"
access to all rows. But you should be cautious here because the field may be accessible through a different type e.g.
the `returning` field in a mutation output type.

:::

### Access only via primary key

Let's say you want to allow a client to fetch data from a table only if the client knows the primary key of a row in
that table.

In this case, regardless of the permission on the table, only `<table>_by_pk` should be exposed in `query_root`.

<Thumbnail
  src="/img/auth/disable-select-root-fields_console_2.11.1.png"
  alt="Disable select root fields in Hasura Console"
  width="600px"
/>

### Disable subscription fields

Allow a role to only be able to make query and not subscription requests.

<Thumbnail
  src="/img/auth/disable-subscription-root-fields_console_2.11.1.png"
  alt="Disable subscription root fields in Hasura Console"
  width="600px"
/>

